# -*- coding: utf-8 -*-
import scopt.test.common
from scopt.mpu.business.settings.handlers import business_partner
from scopt.mpu.business.settings.handlers import address
from scopt.mpu.business.core.handlers import compound_request


class BPCreate(scopt.test.common.ScoptTest):
    ''' Business Partner (BP) creation tests
    MPU should:

    1. test_bp_create_unique
        allow to create BP
    2. test_bp_create_duplicate
        disallow to create BP with same name
    3. test_bp_create_read
        create BP and retrieve it with returned BP entry id
    '''
    def test_bp_create_unique(self):
        # New CUSTOMER is not part of demo data
        request = self.request(business_partner.create)
        request['reqd'] = {'name': 'New CUSTOMER',
                           'is_customer': True,
                           'is_supplier': False}

        response = self.send_request(request)

        self.assertStatus(response, 'OK')

    def test_bp_create_duplicate(self):
        # 'SuperStore / Superobchod' is part of demo data
        request = self.request(business_partner.create)
        request['reqd'] = {'name': 'SuperStore / Superobchod'}

        response = self.send_request(request, pass_interrupts=True)

        self.assertStatus(response, 'INT', 'business.violation.unique_key')

    def test_bp_create_read(self):
        # New CUSTOMER is not part of demo data
        bp_to_create = 'New CUSTOMER'
        create_request = self.request(business_partner.create)
        create_request['reqd'] = {'name': bp_to_create,
                                  'is_customer': True,
                                  'is_supplier': False}

        create_response = self.send_request(create_request)

        select_request = self.request(business_partner.select)
        select_request['reqd'] = {'id': create_response['resd']['id']}

        select_response = self.send_request(select_request)

        select_resd = select_response['resd']
        entry = select_resd[0]

        self.assertStatus(select_response, 'OK')
        self.assertEqual(len(select_resd), 1)
        self.assertEqual(entry['name'], bp_to_create)
        self.assertEqual(entry['is_customer'], True)
        self.assertEqual(entry['is_supplier'], False)


class BPUpdate(scopt.test.common.ScoptTest):
    ''' Business Partner (BP) creation tests
    MPU should:

    1. test_bp_update_new_name
        allow update BP to other unique name
    2. test_bp_update_duplicate_name
        disallow update BP to name which is not unique
    3. test_bp_update_invalid_id
        disallow update BP with invalid id
    4. test_bp_update_missing_id
        disallow update BP with id is missing
    5. test_bp_update_read
        update and read BP by its ID
    '''
    def test_bp_update_new_name(self):
        # BUSINESS PARTNER is not part of demo data
        request = self.request(business_partner.update)
        request['reqd'] = {'id': 1,
                           'name': 'BUSINESS PARTNER',
                           'is_customer': True,
                           'is_supplier': True}

        response = self.send_request(request)

        self.assertStatus(response, 'OK')

    def test_bp_update_duplicate_name(self):
        # SuperStore / Superobchod is not part of demo data
        request = self.request(business_partner.update)
        request['reqd'] = {'id': 1,
                           'name': 'SuperStore / Superobchod'}

        response = self.send_request(request, pass_interrupts=True)

        self.assertStatus(response, 'INT', 'business.violation.unique_key')

    def test_bp_update_invalid_id(self):
        # rows with id over 100 are not part of demo data
        request = self.request(business_partner.update)
        request['reqd'] = {'id': 101,
                           'name': 'SuperStore / Superobchod'}

        response = self.send_request(request, pass_interrupts=True)

        self.assertStatus(response, 'INT', 'business.record_no.is_invalid')

    def test_bp_update_missing_id(self):
        request = self.request(business_partner.update)
        request['reqd'] = {'name': 'SuperStore / Superobchod'}

        response = self.send_request(request, pass_interrupts=True)

        self.assertStatus(response, 'INT', 'business.record_no.is_none')

    def test_bp_update_read(self):
        # In test data row with ID 1 is different from New Customer
        # customer with ID 1 is supplier but not customer
        # we will switch customer supplier roles as well
        db_name_new = 'New CUSTOMER'
        bp_id_to_update = 1
        # 1. assert declared status
        select_request = self.request(business_partner.select)
        select_request['reqd'] = {'id': bp_id_to_update,
                                  'is_customer': False,
                                  'is_supplier': True}

        select_response = self.send_request(select_request)

        row_0 = select_response['resd'][0]

        self.assertStatus(select_response, 'OK')
        self.assertEqual(len(select_response['resd']), 1)
        self.assertNotEqual(row_0['name'], db_name_new)
        self.assertEqual(row_0['is_customer'], False)
        self.assertEqual(row_0['is_supplier'], True)

        # 2. update record
        update_request = self.request(business_partner.update)
        update_request['reqd'] = {'id': bp_id_to_update,
                                  'name': db_name_new,
                                  'is_customer': True,
                                  'is_supplier': False}

        self.send_request(update_request)

        # 3. assert new status
        select_request = self.request(business_partner.select)
        select_request['reqd'] = {'id': bp_id_to_update,
                                  'is_customer': True,
                                  'is_supplier': False}

        select_response = self.send_request(select_request)

        row_0 = select_response['resd'][0]

        self.assertStatus(select_response, 'OK')
        self.assertEqual(len(select_response['resd']), 1)
        self.assertEqual(row_0['name'], db_name_new)
        self.assertEqual(row_0['is_customer'], True)
        self.assertEqual(row_0['is_supplier'], False)


class BPSelect(scopt.test.common.ScoptTest):
    ''' Business Partner (BP) select tests
    MPU should:

    1. test_bp_select_one
        select one BP by bp_id
    2. test_bp_select_all
        select all BPs by not providing id
    3. test_bp_select_none
        select none BP by providing id of non existent record
    '''
    def test_bp_select_one(self):
        request = self.request(business_partner.select)
        request['reqd'] = {'id': 1}

        response = self.send_request(request)

        self.assertEqual(len(response['resd']), 1)

    def test_bp_select_all(self):
        request = self.request(business_partner.select)
        request['reqd'] = {}

        response = self.send_request(request)

        self.assertEqual(len(response['resd']), 3)

    def test_bp_select_none(self):
        request = self.request(business_partner.select)
        request['reqd'] = {'id': 100}

        response = self.send_request(request)

        self.assertEqual(len(response['resd']), 0)


class BPAddress(scopt.test.common.ScoptTest):
    def test_bp_address_add(self):
        request = self.request(business_partner.add_address)
        request['reqd'] = {'business_partner_id': 3,
                           'address_id': 2,
                           'address_type_id': 3,
                           'note': 'Address in some big city'}

        response = self.send_request(request)
        address_id = response['resd']['address_id']
        business_parnter_id = response['resd']['business_partner_id']

        self.assertStatus(response, 'OK')
        self.assertEqual(address_id, request['reqd']['address_id'])
        self.assertEqual(business_parnter_id,
                         request['reqd']['business_partner_id'])

    def test_compound_address_bp_create(self):
        bp_create_request = self.request(business_partner.create)
        address_create_request = self.request(address.create)
        address_create_request = self.\
            __setup_address_request(address_create_request)
        address_add_request = self.request(business_partner.add_address)
        bp_create_request['reqd'] = {'name': 'New PARTNER'}
        address_add_request['reqd'] = {'business_partner_id': '${[0].resd.id}',
                                       'address_id': '${[1].resd.id}',
                                       'address_type_id': 3}
        request = self.request(compound_request.handle)
        request['reqd'] = [bp_create_request,
                           address_create_request,
                           address_add_request]

        response = self.send_request(request)

        self.assertStatus(response, 'OK')
        self.assertEqual(len(response['resd']), 3)
        for partial_response in response['resd']:
            self.assertStatus(partial_response, 'OK')

    def __setup_address_request(self, request):
        request['reqd'] = {'address_line_1': 'LINE 1 of address',
                           'address_line_2': 'LINE 2 of address',
                           'address_line_3': 'LINE 3 of address',
                           'city': 'CITY of address',
                           'state': 'STATE of address',
                           'country': 'COUNTRY of address',
                           'zip': 'ZIP of address'}
        return request

    def test_bp_address_list(self):
        request = self.request(business_partner.address_list)
        request['reqd'] = {'business_partner_id': 2}

        response = self.send_request(request)

        self.assertStatus(response, 'OK')

    def test_bp_address_remove(self):
        request = self.request(business_partner.remove_address)
        request['reqd'] = {'address_id': 1,
                           'business_partner_id': 1}

        response = self.send_request(request)

        self.assertStatus(response, 'OK')

        # Assert database status
        address_request = self.request(address.select)
        address_request['reqd'] = {'id': 1}

        address_response = self.send_request(address_request)

        self.assertEqual(len(address_response['resd']), 0)

        address_request = self.request(address.select)
        address_request['reqd'] = {}

        address_response = self.send_request(address_request)

        self.assertEqual(len(address_response['resd']), 1)

    def test_bp_address_update(self):
        request = self.request(business_partner.update_address)
        request['reqd'] = {'address_id': 1,
                           'business_partner_id': 1,
                           'address_type_id': 1,
                           'note': 'NEW NOTE'}

        response = self.send_request(request)

        self.assertStatus(response, 'OK')

        # Assert database status
        request = self.request(business_partner.address_list)
        request['reqd'] = {'business_partner_id': 1}

        response = self.send_request(request)

        address_entry = response['resd'][0]

        self.assertStatus(response, 'OK')
        self.assertEqual(address_entry['note'], 'NEW NOTE')
        self.assertEqual(address_entry['address_type']['name'],
                         'Warehouse/Sklad')


class BPMedia(scopt.test.common.ScoptTest):
    def test_bp_media_add(self):
        request = self.request(business_partner.add_media)
        request['reqd'] = {'business_partner_id': 2,
                           'media_type_id': 3,
                           'media_contact_id': 1,
                           'note': 'skype of SuperStore'}

        response = self.send_request(request)

        media_contact_id = response['resd']['media_contact_id']
        business_parnter_id = response['resd']['business_partner_id']

        self.assertStatus(response, 'OK')
        self.assertEqual(media_contact_id, request['reqd']['media_contact_id'])
        self.assertEqual(business_parnter_id,
                         request['reqd']['business_partner_id'])

        # Assert database status
        request = self.request(business_partner.media_list)
        request['reqd'] = {'business_partner_id': 2}

        response = self.send_request(request)

        entry = response['resd'][0]
        media_type = entry['media_type']['name']
        note = entry['note']

        self.assertEqual(media_type, 'skype')
        self.assertEqual(note, 'skype of SuperStore')

    def test_bp_media_list(self):
        request = self.request(business_partner.media_list)
        request['reqd'] = {'business_partner_id': 1}

        response = self.send_request(request)

        self.assertEqual(len(response['resd']), 2)

    def test_bp_media_remove(self):
        request = self.request(business_partner.remove_media)
        request['reqd'] = {'business_partner_id': 1,
                           'media_contact_id': 1}

        self.send_request(request)

        # Assert database status
        request = self.request(business_partner.media_list)
        request['reqd'] = {'business_partner_id': 1}

        response = self.send_request(request)

        entry = response['resd'][0]

        self.assertEqual(len(response['resd']), 1)
        self.assertEqual(entry['media_type']['id'], 2)

    def test_bp_media_update(self):
        request = self.request(business_partner.update_media)
        request['reqd'] = {'business_partner_id': 1,
                           'media_contact_id': 1,
                           'media_type_id': 1,
                           'note': 'NEW NOTE'}

        self.send_request(request)

        # Assert database status
        request = self.request(business_partner.media_list)
        request['reqd'] = {'business_partner_id': 1}

        response = self.send_request(request)
        self.assertStatus(response, 'OK')

        contact_entry = response['resd'][0]

        self.assertEqual(contact_entry['note'], 'NEW NOTE')
        self.assertEquals(contact_entry['media_type']['name'], 'email')
